function SpCallback(clientName, id, userPerformDataCallback){
		var _util = Library.WebControl.Util;
    var _hashParameter = Library.WebControl.Hashtable.CreateHashtable();
    var _id = id;
    var _instance = this;
    var _userPerformDataCallback = userPerformDataCallback;   
    _globalHashObject.Add(clientName, _instance);
    window[clientName] = _instance;
    
    
    
    this.AddParameter = function(k, v){
        _hashParameter.Add(k, v);
    };
    function handleCallbackComplete(sender, args){         
        var callbackArgs =  Library.WebControl.Util.ParseAjaxResponse(args.ResponseText);        
        callbackArgs.Parameter = sender.P;
        if (!callbackArgs.IsValid) {
            alert(callbackArgs.Result);
        }
        if (sender.F && typeof(sender.F) == "function") 
            sender.F(_instance, callbackArgs);
        
    };
    
    function createForm(){
        var formId = "simpleDownloadForm";    
        var f = document.getElementById(formId);
        if (f != null && typeof(f) != "undefined") return f;
        f = document.createElement("form");        
        f.setAttribute("name", formId);
        f.setAttribute("id", formId);        
        //f.setAttribute("enctype", "multipart/form-data");
        f.style.position = "absolute";
        f.style.top = "-1000px";
        f.style.left = "-1000px";        
        document.body.appendChild(f);
        return f;
    };

    this.SendDownload = function(p, func){				
        var uf = createForm();
        while(uf.firstChild) {
					uf.removeChild(uf.firstChild);
				}
				var token = new Date().getTime(); 
        _hashParameter.Add("__SPCALLBACKRQP_", "T");
        _hashParameter.Add("__SPAXRQ_", "T");
        _hashParameter.Add("__SPCALLBACKRQDATA_", p);
        _hashParameter.Add("__SPCALLBACKRQSID_", _id);
        _hashParameter.Add("__SPCALLBACKRQDLT_", token);
        _hashParameter.Add("__SPCALLBACKRQTYPE_", "2");//download callback
        var kvs = _hashParameter.GetAll();
        for (var i = 0; i < kvs.length; i++) {
            var id = kvs[i].Id;
            var value = kvs[i].Value;
            var ip = document.createElement('input');
            ip.setAttribute("type", "hidden");
            ip.setAttribute("id", id);
            ip.setAttribute("name", id);
            ip.setAttribute("value", value);
            uf.appendChild(ip);
        }
        _hashParameter.Clear();
        var t = new Date().getTime();
        var action = "";
        if (_spglobalRequestUrl.indexOf("?") >=0) {
					action = _spglobalRequestUrl + "&dt=" + t.toString();
        }else {
					action = _spglobalRequestUrl + "?dt=" + t.toString();
        }
        uf.setAttribute("action", action)
        uf.setAttribute("method", "POST");  
        uf.submit();
        setTimeout(function(){uf.parentNode.removeChild(uf);}, 100);
        if (typeof(func) == "function")
					waitForDownloadComplete(func, token);
    };
    
    function waitForDownloadComplete(f, tk) {
			var ck = _util.GetCookie("spDownloadControlTokenKey");
			if (ck) {
				var rs = _util.ParseArrResponse(ck);
				if(rs[0] == tk) {
					var e = {IsValid:true, Result:rs[1]};
					try {
						f(_instance, e);
					} catch(ex){
						alert(ex);
					}
					_util.DeleteCookie("spDownloadControlTokenKey");
					return;
				}
			}
			setTimeout(function(){waitForDownloadComplete(f, tk);}, 500);
    };
    
    
    this.SendCallback = function(parameter, callbackFunction){
        var ajaxRequest = Library.WebControl.Ajax.CreateRequest();
        if (!_userPerformDataCallback) {
            var ips = ['input', 'select'];
            for (var i = 0; i < ips.length; i++) {
                var ip = document.getElementsByTagName(ips[i]);
                if (ip) {
                    for (var i = 0; i < ip.length; i++) {
                        var input = ip.item(i);
                        if (input.type.toLowerCase() == 'checkbox') {
                            if (input.checked) {
                                _hashParameter.Add(ip.item(i).getAttribute('id'), ip.item(i).value);
                            }
                        }
                        else {
                            _hashParameter.Add(ip.item(i).getAttribute('id'), ip.item(i).value);
                        }
                    }
                }
            }
        }
        var para = '__SPCALLBACKRQP_=T&__SPCALLBACKRQTYPE_=1&__SPCALLBACKRQDATA_=' + encodeURIComponent(parameter) + '&__SPCALLBACKRQSID_=' + _id + '&' + _hashParameter.ToQuery();
        _hashParameter.Clear();
        ajaxRequest.SetData(para);
        ajaxRequest.SendCallback({P:parameter, F:callbackFunction}, handleCallbackComplete);
    };
};
